using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace SharksHunter.Engine.Components.Abstract
{
    public abstract class HunterComponent:SharksHunter.Engine.Interfaces.IHunterComponent
    {
        #region MEMBERS
        protected SyncObject _producerObject;
        protected SyncObject _consumerObject;
        protected Thread _operationThread;
        static private EventWaitHandle _exitThreadEvent = new ManualResetEvent(false);
        #endregion

        #region CTOR
        public HunterComponent()
        {
            _producerObject = new SyncObject(_exitThreadEvent);
            _operationThread = new Thread(ProcessOperations);
        }
        #endregion

        #region Thread
        virtual protected void ProcessOperations()
        {
            int wait = -1;
            while (true)
            {
                wait = WaitHandle.WaitAny(_consumerObject.SyncEvents.EventArray);
                if(wait == 1)//exit thread;
                    return;
                if(wait == 2)//no more new elements, do job and get out
                {
                    break;
                }

                object o = DeQueue();
                o = this.Process(o);
                if(o != null)
                    this.EnQueue(o);
            } 
            while(_consumerObject.Queue.Count > 0)
            {
                object o = DeQueue();
                o = this.Process(o);
                if(o != null)
                    this.EnQueue(o);
            }
            this.SyncObject.SyncEvents.NoMoreJobEvent.Set();
        }
        #endregion

        #region IHunterComponent
        public void DoJob()
        {
            _operationThread.Start();
        }
        public SyncObject SyncObject
        {
            get
            {
                return _producerObject;
            }
        }

        public SyncObject SyncObjectExt
        {
            set
            {
                _consumerObject = value;
            }
        }

        #endregion

        #region PROTECTED

        protected void EnQueue(object o)
        {
            lock (((ICollection)this._producerObject.Queue).SyncRoot)
            {
                _producerObject.Queue.Enqueue(o);
                _producerObject.SyncEvents.NewItemEvent.Set();
            }
        }
        protected object DeQueue()
        {
            object o = null;
            lock (((ICollection)_consumerObject.Queue).SyncRoot)
            {
                o = _consumerObject.Queue.Dequeue();
            }
            return o;
        }

        #endregion

        #region ABSTRACT
        abstract protected object Process(object o);
 
        #endregion
    }
}
